%include "x64kernel/kernel/asm/include/common.inc"

[SECTION .data]
msg_1: db "[time slice] processor id: %d, enter", 10, 13, 0
msg_2: db "[time slice] processor id: %d, no task", 10, 13, 0

lock_state: db 0

[SECTION .text]
[BITS 64]
extern printk
extern send_local_apic_eoi
extern local_apic_clock_run
extern get_task_context
extern resume_task64
extern set_task_ready
extern sched64
extern get_esp0
extern switch_task64

; rip
; cs
; eflags
global time_slice_handler_entry
time_slice_handler_entry:
.check:
    push rdi

    swapgs
    mov rdi, [gs:8]
    swapgs

    cmp rdi, 0
    je .no_store_context
.store_context:
    ; 暂存rax
    push rax

    swapgs
    mov rdi, [gs:8]
    swapgs
    call get_task_context
    mov rdi, rax

    ; 恢复rax
    pop rax

    mov [rdi + 8 * 2], rax
    mov [rdi + 8 * 3], rbx
    mov [rdi + 8 * 4], rcx
    mov [rdi + 8 * 5], rdx
;    mov [rdi + 8 * 6], rdi         ; 在后面保存
    mov [rdi + 8 * 7], rsi
    mov [rdi + 8 * 8], rbp
;    mov [rdi + 8 * 9], rsp         ; 当前的rsp是cpu自动压入三个值之后的
    mov [rdi + 8 * 10], r8
    mov [rdi + 8 * 11], r9
    mov [rdi + 8 * 12], r10
    mov [rdi + 8 * 13], r11
    mov [rdi + 8 * 14], r12
    mov [rdi + 8 * 15], r13
    mov [rdi + 8 * 16], r14
    mov [rdi + 8 * 17], r15

    mov rcx, rdi

.store_rdi:
    pop rax
    mov [rcx + 8 * 6], rax

    ; rip在堆栈里，程序无法访问rip
.strore_rip:
    mov rax, [rsp + 8 * 0]
    mov [rcx + 8 * 1], rax

    ; cs也在堆栈
.store_cs:
    mov rax, [rsp + 8 * 1]
    mov [rcx + 8 * 18], rax

    ; rflags也在堆栈里
.store_rflags:
    mov rax, [rsp + 8 * 2]
    mov [rcx], rax

.store_rsp:
    ; 因为堆栈里push了rip，cs和rflags
    mov rax, rsp
    add rax, 8 * 3
    mov [rcx + 8 * 9], rax

.set_task_ready:
    swapgs
    mov rdi, [gs:8]
    swapgs
    call set_task_ready

.find_ready_task:
    call sched64
    cmp rax, 0
    je .no_ready_task

.store_ready_task:
    swapgs
    mov [gs:8], rdi
    swapgs

.resume_task64:
    swapgs
    mov rdi, [gs:8]
    swapgs
    call get_task_context

    mov rbx, [rax + 8 * 3]
    mov rcx, [rax + 8 * 4]
    mov rdx, [rax + 8 * 5]
    mov rdi, [rax + 8 * 6]
    mov rsi, [rax + 8 * 7]
    mov r8, [rax + 8 * 10]
    mov r9, [rax + 8 * 11]
    mov r10, [rax + 8 * 12]
    mov r11, [rax + 8 * 13]
    mov r12, [rax + 8 * 14]
    mov r13, [rax + 8 * 15]
    mov r14, [rax + 8 * 16]
    mov r15, [rax + 8 * 17]

    mov rbp, [rax + 8 * 8]
    mov rsp, [rax + 8 * 9]

    push qword [rax]              ; rflags
    push qword [rax + 8 * 18]      ; cs

    ; rip
    push qword [rax + 8]          ; rip
    mov rax, [rax + 8 * 2]          ; 恢复rax

    call local_apic_clock_run
    call send_local_apic_eoi

    iretq                     ; 返回前两句push的代码位置

.no_store_context:
    pop rdi

    call sched64
    cmp rax, 0
    je .no_ready_task

    mov rdi, rax
    call get_esp0

    swapgs
    mov [gs:8], rdi
    mov [gs:32], rax
    swapgs

    call switch_task64

    iretq

.no_ready_task:
    call send_local_apic_eoi
    iretq